package descentFly
{
	import away3d.core.base.SubGeometry;
	import away3d.core.base.SubMesh;
	import away3d.core.math.Matrix3DUtils;
	import away3d.entities.Mesh;
	import away3d.tools.utils.Bounds;
	import away3d.tools.utils.Ray;
	import away3d.vf.managers.awayLoadSection;
	import away3d.vf.managers.loadSection;
	
	import descentFly.app.df_managePanel;
	import descentFly.app.df_topTollbar;
	import descentFly.away3D4.df_loadSection;
	import descentFly.data.df_classes;
	import descentFly.view.df_view;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	
	import jiglib.math.JMatrix3D;
	
	import space.sp_utils;

	public class df_utils {
		
		public static function objToMatrix(obj: Object): Matrix3D {
			var pos: Vector3D = objToPosition(obj);
			
			var transform:Matrix3D = JMatrix3D.getTranslationMatrix(pos.x, pos.y, pos.z);
			transform = JMatrix3D.getAppendMatrix3D(objToOrientation(obj), transform);
			return transform;
		}
		
		public static function objToOrientation(obj: Object): Matrix3D {
			var mat: Matrix3D = new Matrix3D();
			if (obj && obj.orientation) {
				mat.appendRotation(obj.orientation[0], Vector3D.X_AXIS);
				mat.appendRotation(obj.orientation[1], Vector3D.Y_AXIS);
				mat.appendRotation(obj.orientation[2], Vector3D.Z_AXIS);
			}
			return mat;
		}
		
		public static function matToObject(mat: Matrix3D): Object {
			var nv	: Vector3D = new Vector3D();
			var p	: Vector3D = mat.transformVector(nv);
			var rm	: Matrix3D = mat.clone();
			rm.appendTranslation(-p.x, -p.y, -p.z);
			
			return {
				position	: p,
				orientation	: rm
			}
		}
		
		public static function toVector(v: Object): Vector3D {
			if (v) {
				if (v.hasOwnProperty('x')) return new Vector3D(v.x, v.y, v.z);
				else if (v is Array) return new Vector3D(v[0], v[1], v[2]);
				else if (v is String) {
					var a: Array = v.split(',');
					return new Vector3D(a[0], a[1], a[2]);
				}
			}
			return new Vector3D();
		}

		public static function objToPosition(obj: Object): Vector3D {
			if (obj && obj.position) {
				return new Vector3D(obj.position[3], obj.position[4], obj.position[5]);
			}
			return new Vector3D();
		}
		
		public static function hitTestSubMesh(subMesh: SubMesh, p1: Vector3D, p2: Vector3D): Vector3D {
			var ray		: Ray 	= new Ray();
			var v		: Array = new Array();
			
			faceForEach(subMesh, function(face: Array, inx: Array): void {
				var vv: Vector3D = ray.getRayToTriangleIntersection(p1, p2, face[0], face[2], face[1])
//				var vv: Vector3D = ray.getIntersect(p1, p2, face[0], face[2], face[1])
				if (vv) v.push(vv.clone());
			});
			
			
			if (v.length > 0) { // Выбираем самый ближний вектор
				if (v.length == 1) return v[0];
				var result	: Vector3D;
				var min		: Number = Number.MAX_VALUE;
				for (var i: int=0; i<v.length; i++)	
					if (v[i].length < min) {
						min = v[i].length;
						result = v[i];
					}
				return result;
			} else return null;
		}
		
		public static function faceForEach(subMesh: SubMesh, process: Function): Object {
			var subGeom 	: SubGeometry = subMesh.subGeometry;
			var indices 	: Vector.<uint> 	= subGeom.indexData;
			var vertices 	: Vector.<Number> 	= subGeom.vertexData;
			var len 		: int = indices.length;
			var i 			: uint = 0, j : uint = 1, k : uint = 2;
			var t1 			: uint, t2 : uint, t3 : uint;
			
			while (i < len) {
				t1 = indices[i]*3;
				t2 = indices[j]*3;
				t3 = indices[k]*3;
				var value: Object = process([
					new Vector3D(vertices[t1], vertices[t1+1], vertices[t1+2]),
					new Vector3D(vertices[t2], vertices[t2+1], vertices[t2+2]),
					new Vector3D(vertices[t3], vertices[t3+1], vertices[t3+2])
				], [t1, t2, t3]);
				if (value) return value;
				i += 3;
				j += 3;
				k += 3;
			}
			return null;
		}
		
		public static function matToArray(mat: Matrix3D): Array {
			var result: Array = new Array();
			for (var i:int=0; i<16; i++) {
				result.push(mat.rawData[i]);
			}
			return result;
		}

		public static function arrToMat(arr: Array): Matrix3D {
			return new Matrix3D(Vector.<Number>(arr));
		}
		
		
		/*
			info: {
				imageURL	: 'image.png',
				sprite		: {
					width	: 120,
					height	: 120
				}
			}
		*/
		public static function loadFramesOneImage(info: Object, doComplete: Function, param: Object=null): void {
			var _ls: df_loadSection = new df_loadSection();
			
			var bmp: Bitmap = _ls.loadBmp(info.imageURL, true);
			
			_ls.endSection(function(): void {
				var _frames: Array = new Array();
				var y: Number = 0;
				while (y < bmp.bitmapData.height) {
					var x: Number = 0;
					while (x < bmp.bitmapData.width) {
						var _frame: Bitmap = new Bitmap(new BitmapData(info.sprite.width, info.sprite.height, true, 0));
						var mat: Matrix = new Matrix();
						mat.translate(-x, -y);
						_frame.bitmapData.draw(bmp, mat);
						_frames.push(_frame);
						
						x += info.sprite.width;
					}
					y += info.sprite.height;
				}
				doComplete(info, _frames, param);
			});
		}
		
		/*
			info: {
				frames		:  16,
				filePattern	: 'image%d.png'
			}
		*/
		public static function loadFrames(info: Object, doComplete: Function, param: Object=null): void {
			var _frames: Array = new Array();
			var _ls: df_loadSection = new df_loadSection();
			for (var i: int=1; i<=info.frames; i++) {
				_frames.push(_ls.loadBmp(info.filePattern.replace('%d', i), true));
			}
			
			_ls.endSection(function(): void {
				doComplete(info, _frames, param);
			});
		}
		
		public static function itemFromID(arr: Array, id: uint): Object {
			var result: Object = null;
			arr.forEach(function(item: Object, i: int, arr: Array): void {
				if (item.id == id) result = item;
			});
			return result;
		}
		
		public static function rectDivX(rect: Rectangle, div: Number, space: Number = 0): Array {
			var result: Array = new Array();
			result[0] = new Rectangle(rect.x, rect.y, rect.width * div - space / 2, rect.height);
			result[1] = new Rectangle(result[0].right + space, rect.y, 
									rect.width - result[0].width - space, rect.height);
			
			return result;
		}
		
		public static function rectDivY(rect: Rectangle, div: Number, space: Number = 0): Array {
			var result: Array = new Array();
			result[0] = new Rectangle(rect.x, rect.y, rect.width, rect.height * div - space / 2);
			result[1] = new Rectangle(rect.x, result[0].bottom + space, 
				rect.width, rect.height - result[0].height - space);
			return result;
		}
		
		public static function callWaitEvent(dispacher: IEventDispatcher, event: String, func: Function): void {
			function doEvent(e: Event): void {
				dispacher.removeEventListener(event, doEvent);
				func();
			}
			dispacher.addEventListener(event, doEvent);
		}
		
		public static function callWaitEvent2(dispacher: IEventDispatcher, noWait: Boolean, event: String, func: Function): void {
			if (noWait) func()
			else callWaitEvent(dispacher, event, func);
		}
		
		public static function maxSize(mesh: Mesh): Number {
			Bounds.getMeshBounds(mesh);
			return Math.max(Bounds.width, Math.max(Bounds.height, Bounds.depth));
		}
	}
}